package cn.coufran.springboot.starter.api.config;

import cn.coufran.commons.Result;
import cn.coufran.springboot.starter.api.NoWrap;
import com.alibaba.fastjson2.support.spring6.http.converter.FastJsonHttpMessageConverter;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Method;

/**
 * 使用Result包装返回的对象，除非返回的就是Result或者标记了不需要包装
 * @author Coufran
 * @version 2.0.0
 * @since 1.0.0
 */
@RestControllerAdvice
public class ResponseHandler implements ResponseBodyAdvice<Object> {

    /**
     * 是否支持
     * @param methodParameter MethodParameter
     * @param converterType 转换器类型
     * @return 支持返回true
     */
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> converterType) {
        return converterType == FastJsonHttpMessageConverter.class;
    }

    /**
     * 转换Body
     * @param body Body
     * @param methodParameter MethodParameter
     * @param selectedContentType ContentType
     * @param selectedConverterType 转换器类型
     * @param request Request
     * @param response Response
     * @return 转换后的Body
     */
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        // 如果是ErrorController的方法，不需要包装
        Method method = methodParameter.getMethod();
        if (ErrorController.class.isAssignableFrom(method.getDeclaringClass())) {
            return body;
        }

        // 判断不需要包装标记
        NoWrap noWrap = methodParameter.getMethodAnnotation(NoWrap.class);
        if (noWrap != null) {
            return body;
        }
        // 是否已经是Result对象
        if(body instanceof Result) {
            return body;
        }
        // 其他情况，一概包装
        return Result.ok(body);
    }
}